<?php
namespace App\Wen\Utils;

use App\Jobs\System\AlipayTradeRefundQueryJob;
use App\Jobs\System\CheckBatchCahceDataLossJob;
use App\Models\Bureau\WxClubTeam;
use App\Models\Shop\WxShop;
use App\Models\Shop\WxShopCart;
use App\Models\Shop\WxShopClassify;
use App\Models\Shop\WxShopContact;
use App\Models\Shop\WxShopFollow;
use App\Models\Shop\WxShopGoods;
use App\Models\Shop\WxShopGoodsProduct;
use App\Models\Shop\WxShopOrder;
use App\Models\Shop\WxShopOrderAfter;
use App\Models\Shop\WxShopOrderCoupon;
use App\Models\Shop\WxShopOrderGoods;
use App\Models\Used\WxUsedClassify;
use App\Models\Used\WxUsedComment;
use App\Models\Used\WxUsedGood;
use App\Models\Used\WxUsedNeed;
use App\Models\User\WxUserFinancialFreeze;
use App\Models\User\WxUserVisit;
use App\Models\WxDomainAuth;
use App\Models\WxRefund;
use Carbon\Carbon;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Yansongda\Pay\Pay;

class ShopUtils{
    private static $ban_shop_classes = null;

    public static function get_user_coupon($uid, $order_id, $status = [0, 1]){
        if(_empty_($uid) || _empty_($order_id)){
            return null;
        }
        $order = WxShopOrder::where([
            ['id', '=', $order_id],
            ['user_id', '=', $uid],
            ['pay_status', '=', 2],
//            ['status', '=', 1]
        ])->first();
        if($order){
            $coupon = WxShopOrderCoupon::where([
                ['user_id', '=', $uid],
                ['order_id', '=', $order_id],
            ])->whereIn('status', $status)->first();
            if($coupon){

            }else{
                $code = Utils::getSn(12);
                $bar_code_url = ImageUtils::code($code, 'bar');
                $qr_code_url = ImageUtils::code('shop:order:coupon:'.$code, 'qr');
                if($bar_code_url && $qr_code_url){
                    $coupon = new WxShopOrderCoupon();
                    $coupon->user_id = $uid;
                    $coupon->order_id = $order_id;
                    $coupon->code = $code;
                    $coupon->qrcode = $qr_code_url;
                    $coupon->barcode = $bar_code_url;
                    $coupon->status = 0;
                    $coupon->save();
                }else{
                    return null;
                }
            }
            if($order->status != 1){
                if($order->status === 0){
                    return null;
                }
                $coupon->status = 2;
                $coupon->save();
            }
            $status_tip_arr = [
                0 => '待使用',
                1 => '已核销',
                2 => '已失效'
            ];
            $coupon->code_tip = implode(' ', str_split($coupon->code, 4));
            $coupon->status_tip = $status_tip_arr[$coupon->status];
            return $coupon;
        }else{
            return null;
        }
    }

    public static function get_expree_name_range(){
        return [
            [
                'name' => '邮政包裹',
                'type' => 'CHINAPOST'
            ],
            [
                'name' => '邮政速递物流',
                'type' => 'EMS'
            ],
            [
                'name' => '顺丰',
                'type' => 'SFEXPRESS'
            ],
            [
                'name' => '极兔速递',
                'type' => 'JITU'
            ],
            [
                'name' => '圆通快递',
                'type' => 'YTO'
            ],
            [
                'name' => '申通快递',
                'type' => 'STO'
            ],
            [
                'name' => '中通快递',
                'type' => 'ZTO'
            ],
            [
                'name' => '韵达快递',
                'type' => 'YUNDA'
            ],
            [
                'name' => '百世快递',
                'type' => 'HTKY'
            ],
            [
                'name' => '天天快递',
                'type' => 'TTKDEX'
            ],


            [
                'name' => '韵达快运',
                'type' => 'YUNDA56'
            ],
            [
                'name' => '百世快运',
                'type' => 'BSKY'
            ],
            [
                'name' => '中通快运',
                'type' => 'ZTO56'
            ],
        ];
    }


    public static function order_unpack_products($order_id, $order_goods_id){
        if(_empty_($order_id) || _empty_($order_goods_id) || !is_array($order_goods_id)){
            throw new \Exception('参数错误');
        }



    }


    public static function order_good_refund($order_good_id){
        // 这里包括了管理员强制退款，也就是用户并没有申请退款，但管理员强行退

        // 代表正常余额退或者金币退
        $last_order_good_state = 3;

        $oginfo = WxShopOrderGoods::where('id', $order_good_id)->first();
        $user_id = WxShopOrder::where('id', $oginfo['order_id'])->value('user_id');
        $app_coin_name = Settings::get('app_coin_name', '硬币');
        if($oginfo && $user_id > 0 && in_array($oginfo->state, [0, 1, 2]) && $oginfo->recharge > 0 && !WxRefund::where('order_good_id', $order_good_id)->exists()){
            DB::beginTransaction();
            try {
                $order_id = $oginfo->order_id;
                $shop_order = WxShopOrder::where('id', $oginfo['order_id'])->first();
                if($oginfo->credit_type == 1){
                    if($shop_order->coins_pay > 0){
                        $coin_rate = $shop_order->coins_num / $shop_order->coins_pay;
                        if($shop_order->coins_pay >= $oginfo->recharge){
                            // 全部以金币退
                            if($shop_order->coins_pay - $oginfo->recharge > 0.01){
                                $need_refund_coins = (int)($oginfo->recharge * $coin_rate);
                                $nr = '您购买的：「' . $oginfo['name'] . '(规格：' . $oginfo['product'] . ')」×' . $oginfo['quantity'] . '件的售后申请已处理完毕，其中￥'.$oginfo->recharge.'已退款('.$need_refund_coins.Settings::get('app_coin_name', '硬币').')';
                                // 退款记录
                                $refund_record = new WxRefund();
                                $refund_record->user_id = $user_id;
                                $refund_record->order_good_id = $oginfo->id;
                                $refund_record->order_id = $oginfo->order_id;
                                $refund_record->goods_id = $oginfo->goods_id;
                                $refund_record->product_id = $oginfo->product_id;
                                $refund_record->amount = $oginfo->recharge;
                                $refund_record->goods_type = $oginfo->goods_type;
                                $refund_record->save();
                                // 增加金币
                                UserUtils::update_user_coins($user_id,4, $need_refund_coins,
                                    '您收到了一笔来自「' . $oginfo['name'] . '(规格：' . $oginfo['product'] . ')」×' . $oginfo['quantity'] . '件的退款，退款' . Settings::get('app_coin_name', '硬币') . $need_refund_coins.'(￥'.$oginfo->recharge.')'
                                );
                                WxShopOrder::where('id', $oginfo['order_id'])->update(['coins_num'=>($shop_order->coins_num - $need_refund_coins), 'coins_pay'=> ($shop_order->coins_pay - $oginfo->recharge) ]);

                                UserUtils::add_user_notice(6002, $user_id, '商品售后通知', $nr, 100);
                            }else{
                                $nr = '您购买的：「' . $oginfo['name'] . '(规格：' . $oginfo['product'] . ')」×' . $oginfo['quantity'] . '件的售后申请已处理完毕，其中￥'.$oginfo->recharge.'已退款('.$shop_order->coins_num. Settings::get('app_coin_name', '硬币'). ')';
                                // 退款记录
                                $refund_record = new WxRefund();
                                $refund_record->user_id = $user_id;
                                $refund_record->order_good_id = $oginfo->id;
                                $refund_record->order_id = $oginfo->order_id;
                                $refund_record->goods_id = $oginfo->goods_id;
                                $refund_record->product_id = $oginfo->product_id;
                                $refund_record->amount = $oginfo->recharge;
                                $refund_record->goods_type = $oginfo->goods_type;
                                $refund_record->save();

                                // 增加金币
                                UserUtils::update_user_coins($user_id,4, $shop_order->coins_num,
                                    '您收到了一笔来自「' . $oginfo['name'] . '(规格：' . $oginfo['product'] . ')」×' . $oginfo['quantity'] . '件的退款，退款' . Settings::get('app_coin_name', '硬币') . $shop_order->coins_num.'(￥'.$shop_order->coins_pay.')'
                                );
                                WxShopOrder::where('id', $oginfo['order_id'])->update(['coins_num'=>0, 'coins_pay'=>0]);

                                UserUtils::add_user_notice(6002, $user_id, '商品售后通知', $nr, 100);
                            }
                        }else{
                            // 退部分金币，部分余额
                            $need_refund_blance = $oginfo->recharge - $shop_order->coins_pay;
                            $nr = '您购买的：「' . $oginfo['name'] . '(规格：' . $oginfo['product'] . ')」×' . $oginfo['quantity'] . '件的售后申请已处理完毕，其中￥'.$oginfo->recharge.'已退款('.$shop_order->coins_num. Settings::get('app_coin_name', '硬币') .'+'.($need_refund_blance).'余额)';
                            // 退款记录
                            $refund_record = new WxRefund();
                            $refund_record->user_id = $user_id;
                            $refund_record->order_good_id = $oginfo->id;
                            $refund_record->order_id = $oginfo->order_id;
                            $refund_record->goods_id = $oginfo->goods_id;
                            $refund_record->product_id = $oginfo->product_id;
                            $refund_record->amount = $oginfo->recharge;
                            $refund_record->goods_type = $oginfo->goods_type;
                            $refund_record->save();

                            $financial_type = 3;
                            if($oginfo->goods_type == 7){
                                $financial_type = 29;
                            }

                            // 增加金币
                            UserUtils::update_user_coins($user_id, 4, $shop_order->coins_num,
                                '您收到了一笔来自「' . $oginfo['name'] . '(规格：' . $oginfo['product'] . ')」×' . $oginfo['quantity'] . '件的退款，退款' . Settings::get('app_coin_name', '硬币') . $shop_order->coins_num.'(￥'.$shop_order->coins_pay.')'
                            );
                            // 增加余额
                            UserUtils::update_user_financial($user_id,$financial_type, $need_refund_blance,
                                '您收到了一笔来自「' . $oginfo['name'] . '(规格：' . $oginfo['product'] . ')」×' . $oginfo['quantity'] . '件的退款，退款金额¥' . $need_refund_blance
                            );
                            WxShopOrder::where('id', $oginfo['order_id'])->update(['coins_num'=>0, 'coins_pay'=>0]);

                            UserUtils::add_user_notice(6002, $user_id, '商品售后通知', $nr, 100);
                        }
                    }else{
                        if($oginfo['recharge'] > 0){
                            $refund_flag = 1;
                            $nr = '您购买的：「' . $oginfo['name'] . '(规格：' . $oginfo['product'] . ')」×' . $oginfo['quantity'] . '件的退款申请已处理完毕';
                            // 先尝试原路退回, 如果得到的状态是 处理中 或者 成功， 则代表
                            if($shop_order->serial_platform === 0){

                                $out_trade_no = $shop_order->order_id;
                                $out_refund_no = Utils::getSn(13);
                                $config = json_decode(Cache::get('app_pay_config'), true);
                                if(_empty_($config)){
                                    CheckBatchCahceDataLossJob::dispatch();
                                }
                                $outTradeNoPre = Utils::outTradeNoPre($out_trade_no, 'wx_shoporder_');
                                $config['wechat']['default']['return_url'] = route('pay.return', ['out_trade_no'=>$outTradeNoPre]);
                                $actionMap = [
                                    'mini' => 'miniapp',
                                    'app' => 'app',
                                    'h5' => 'h5',
                                    'mp' => 'jsapi',
                                    'code' => 'native',
                                    'code_pc' => 'native'
                                ];
                                $order = [
                                    'out_trade_no' => $out_trade_no,
                                    'out_refund_no' => $out_refund_no,
                                    'amount' => [
                                        'refund' => $oginfo['recharge'] * 100,
                                        'total' => $shop_order->payed * 100,
                                        'currency' => 'CNY',
                                    ],
                                    '_action' => _array_key($actionMap, _empty_default_($shop_order->serial_platform_type, 'mini'), 'miniapp'),

                                ];
                                $result = Pay::wechat($config)->refund($order);
                                if($result->status == 'PROCESSING'){
                                    $refund_flag = 0;
                                    $last_order_good_state = 5;
                                    WxShopOrderGoods::where('id', $oginfo['id'])->update([
                                        'refund_no' => $result->out_refund_no,
                                        'state' => 5
                                    ]);
                                }else if($result->status == 'SUCCESS'){

                                    $refund_flag = 0;
                                    // 退款记录
                                    $refund_record = new WxRefund();
                                    $refund_record->user_id = $user_id;
                                    $refund_record->order_good_id = $oginfo->id;
                                    $refund_record->order_id = $oginfo->order_id;
                                    $refund_record->goods_id = $oginfo->goods_id;
                                    $refund_record->product_id = $oginfo->product_id;
                                    $refund_record->amount = $oginfo->recharge;
                                    $refund_record->goods_type = $oginfo->goods_type;
                                    $refund_record->save();

                                    WxShopOrderGoods::where('id', $oginfo['id'])->update([
                                        'refund_no' => $result->out_refund_no,
                                        'state' => 3,
                                        'refund_from' => 0,
                                        'refund_amount' => $result->amount['refund'] / 100,
                                        'refund_time' => Utils::strTimeFormat($result->success_time),
                                        'refund_account' => $result->user_received_account
                                    ]);
                                    UserUtils::add_user_notice(6002, $user_id, '商品退款通知', $nr, 100);

                                }else if($result->status == 'CLOSED' || $result->status == 'ABNORMAL'){
                                    // 继续余额退
                                }
                            }else if($shop_order->serial_platform === 1){
                                $out_trade_no = $shop_order->order_id;
                                $out_refund_no = Utils::getSn(13);
                                $config = json_decode(Cache::get('app_pay_config'), true);
                                if(_empty_($config)){
                                    CheckBatchCahceDataLossJob::dispatch();
                                }
                                $outTradeNoPre = Utils::outTradeNoPre($out_trade_no, 'ali_shoporder_');
                                $config['alipay']['default']['return_url'] = route('pay.return', ['out_trade_no'=>$outTradeNoPre]);
                                $config['alipay']['default']['notify_url'] = env('APP_URL'). '/api/v1/app/ali/notify/app';

                                $actionMap = [
                                    'mini' => 'mini',
                                    'app' => 'app',
                                    'h5' => 'h5',
                                    'pos' => 'pos',
                                    'code' => 'scan',
                                    'code_pc' => 'scan'
                                ];

                                $result = Pay::alipay()->refund([
                                    'out_trade_no' => $out_trade_no,
                                    'refund_amount' => $oginfo['recharge'],
                                    'out_request_no' => $out_refund_no,
                                    '_action' => _array_key($actionMap, _empty_default_($shop_order->serial_platform_type, 'app'), 'app'),
                                ]);

                                if($result && $result->alipay_trade_refund_response){
                                    $result = $result->alipay_trade_refund_response;
                                    // 代表请求成功
                                    if($result['code'] == 10000 || $result['msg'] == 'Success'){
                                        if(_array_key($result, 'fund_change', '') == 'Y'){
                                            $refund_flag = 0;
                                            // 退款记录
                                            $refund_record = new WxRefund();
                                            $refund_record->user_id = $user_id;
                                            $refund_record->order_good_id = $oginfo->id;
                                            $refund_record->order_id = $oginfo->order_id;
                                            $refund_record->goods_id = $oginfo->goods_id;
                                            $refund_record->product_id = $oginfo->product_id;
                                            $refund_record->amount = $oginfo->recharge;
                                            $refund_record->goods_type = $oginfo->goods_type;
                                            $refund_record->save();

                                            $refund_amount = $oginfo['recharge'];
                                            if(_array_key($result, 'refund_charge_info_list', [])){
                                                if(_array_key($result['refund_charge_info_list'][0], 'refund_charge_fee', null)){
                                                    $refund_amount = $result['refund_charge_info_list'][0]['refund_charge_fee'];
                                                }
                                            }

                                            WxShopOrderGoods::where('id', $oginfo['id'])->update([
                                                'refund_no' => $out_refund_no,
                                                'state' => 3,
                                                'refund_from' => 1,
                                                'refund_amount' => $refund_amount,
                                                'refund_time' => current_time(),
                                                'refund_account' => ''
                                            ]);
                                            UserUtils::add_user_notice(6002, $user_id, '商品退款通知', $nr, 100);
                                        }else{
                                            $refund_flag = 0;
                                            $last_order_good_state = 6;
                                            WxShopOrderGoods::where('id', $oginfo['id'])->update([
                                                'refund_no' => $out_refund_no,
                                                'state' => 6
                                            ]);
                                            AlipayTradeRefundQueryJob::dispatch($out_trade_no, $out_refund_no, 20)->delay(now()->addSeconds(10));
                                        }
                                    }
                                }

                            }

                            if($refund_flag === 1){
                                // 退款记录
                                $refund_record = new WxRefund();
                                $refund_record->user_id = $user_id;
                                $refund_record->order_good_id = $oginfo->id;
                                $refund_record->order_id = $oginfo->order_id;
                                $refund_record->goods_id = $oginfo->goods_id;
                                $refund_record->product_id = $oginfo->product_id;
                                $refund_record->amount = $oginfo->recharge;
                                $refund_record->goods_type = $oginfo->goods_type;
                                $refund_record->save();

                                $financial_type = 3;
                                if($oginfo->goods_type == 7){
                                    $financial_type = 29;
                                }
                                // 增加余额
                                UserUtils::update_user_financial($user_id,$financial_type, $oginfo->recharge,
                                    '您收到了一笔来自「' . $oginfo['name'] . '(规格：' . $oginfo['product'] . ')」×' . $oginfo['quantity'] . '件的退款，退款金额¥' . $oginfo->recharge
                                );
                                UserUtils::add_user_notice(6002, $user_id, '商品退款通知', $nr, 100);
                            }

                        }
                    }
                }else if($oginfo->credit_type == 0){
                    $nr = '您购买的：「' . $oginfo['name'] . '(规格：' . $oginfo['product'] . ')」×' . $oginfo['quantity'] . '件的售后申请已处理完毕，其中'.$oginfo->recharge.$app_coin_name.'已退款';
                    // 退款记录
                    $refund_record = new WxRefund();
                    $refund_record->user_id = $user_id;
                    $refund_record->order_good_id = $oginfo->id;
                    $refund_record->order_id = $oginfo->order_id;
                    $refund_record->goods_id = $oginfo->goods_id;
                    $refund_record->product_id = $oginfo->product_id;
                    $refund_record->amount = $oginfo->recharge;
                    $refund_record->goods_type = $oginfo->goods_type;
                    $refund_record->credit_type = 0;
                    $refund_record->save();


                    $coin_type = 27;
                    if($oginfo->goods_type == 7){
                        $coin_type = 26;
                    }

                    // 增加金币
                    UserUtils::update_user_coins($user_id, $coin_type, $oginfo->recharge,
                        '您收到了一笔来自「' . $oginfo['name'] . '(规格：' . $oginfo['product'] . ')」×' . $oginfo['quantity'] . '件的退款，退款' . $app_coin_name .'+'. $oginfo->recharge
                    );
//                        WxShopOrder::where('id', $oginfo['order_id'])->update(['coins_num'=>0, 'coins_pay'=>0]);
                    UserUtils::add_user_notice(6002, $user_id, '商品售后通知', $nr, 100);
                }

                if($last_order_good_state == 3){
                    $updated_at = Carbon::now();
                    WxShopOrderGoods::where('id', $order_good_id)->update([
                        'state' => $last_order_good_state,
                        'updated_at' => $updated_at
                    ]);
                    // 更新订单数据，如果该订单内包含的全部商品都已经退款，则更新该订单的支付状态为：已退款，订单状态为：已退货。
                    $result_ = DB::table('wx_shop_order_goods as wg')
                        ->select(DB::raw('COUNT(*) as total_count, SUM(CASE WHEN state = 3 THEN 1 ELSE 0 END) as state_3_count'))
                        ->where('wg.order_id', $order_good_id)
                        ->first();

                    if ($result_->total_count == $result_->state_3_count) {
                        WxShopOrder::where('id', $order_id)->update([
                            'pay_status' => 3,
                            'status' => 4,
                            'updated_at' => $updated_at
                        ]);
                    }

                    if(in_array($oginfo['goods_type'], FieldUtils::getShopGoodTypes())){
                        WxShopGoods::where('id', $oginfo['goods_id'])->decrement('buys', (int)($oginfo['quantity']));
                        WxShopGoodsProduct::where('id', $oginfo['product_id'])->increment('stock', (int)($oginfo['quantity']));
                    }else{
                        if($oginfo['goods_type'] == 6){
                            WxUsedGood::where('id', $oginfo['goods_id'])->update([
                                'status' => 6
                            ]);
                        }else if($oginfo['goods_type'] == 7){
                            $team = WxClubTeam::find($oginfo['product_id']);
                            if ($team) {
                                $members_arr = $team->members; // 获取当前成员数组
                                if($members_arr){
                                    $key = array_search((int)$oginfo['buyer_user_id'], $members_arr);
                                    if ($key !== false) {
                                        unset($members_arr[$key]);
                                        // 设置并保存成员数组，确保触发属性修改器和事件
                                        $members = array_unique($members_arr);
                                        $team->members = $members;
                                        $team->members_num = count($members);
                                        $team->save();
                                        Cache::forget('get_join_info:'.$team->bureau_id.':'.$oginfo['buyer_user_id']);
                                        Cache::forget('bureau:avatars:'.$team->bureau_id);
                                    }
                                }
                            }
                        }
                    }
                }

                DB::commit();
                return true;
            } catch (\Exception $e) {
                DB::rollBack();
                _logger_(__file__, __line__, $e->getMessage());
                return false;
            }
        }else{
            return false;
        }
    }


    public static function get_ban_classes($device){
        if(self::$ban_shop_classes === null){
            $ban_device_status = [0];
            if(is_mini_examine_mode(11)){
                $ban_device_status[] = 2;
            }
            $ban_ids = WxShopClassify::whereIn('in_'.$device, $ban_device_status)->pluck('id')->toArray();
            if($ban_ids){
                self::$ban_shop_classes = $ban_ids;
            }else{
                self::$ban_shop_classes = [];
            }
        }
        return self::$ban_shop_classes;
    }

    public static function user_buy_goods_times($user_id, $goods_id){
        if(_empty_($user_id) || _empty_($goods_id)){
            return 0;
        }

        return WxShopOrderGoods::where([['goods_id','=', $goods_id], ['state', '=', 0]])->where(function ($query) {
            $query->select('user_id')->from('wx_shop_order')
                ->whereColumn('wx_shop_order_goods.order_id', 'wx_shop_order.id')->where('pay_status', '=', 2);
        }, $user_id)->sum('quantity');
    }


    public static function get_goods_seller_division($orderGood){
        if($orderGood->goods_type == 6){
            return max((100 - Settings::get('app_used_order_division', 1.0)), 0);
        }else if($orderGood->goods_type == 7){
            return max((100 - Settings::get('app_bureau_order_division', 1.0)), 0);
        }else{
            $users_ledger = WxShopGoods::where('id', $orderGood->goods_id)->value('users_ledger');
            $users_ledger_rate_total = 0;
            if(!_empty_($users_ledger)) {
                $users_ledger = json_decode($users_ledger, true);
                if (!_empty_($users_ledger)) {
                    foreach ($users_ledger as $item) {
                        if (_array_key($item, 'user_id', 0) > 0 || _array_key($item, 'rate', 0) > 0) {
                            $users_ledger_rate_total += _array_key($item, 'rate', 0);
                        }
                    }
                    if($users_ledger_rate_total > 100){
                        _logger_(__file__, __line__, '商品的用户分账'.$orderGood->goods_id.'设置不合理，已超过100%');
                    }
                }
            }
            $platform_division = 0;
            $classify_id = WxShopGoods::where('id', $orderGood->goods_id)->value('classify_id');
            if($classify_id > 0){
                $platform_division = WxShopClassify::where('id', $classify_id)->value('platform_division');
                if($platform_division > 100){
                    _logger_(__file__, __line__, '商品分类'.$classify_id.'的平台分成设置错误，超过100');
                }
            }
            return max((100 - $users_ledger_rate_total - $platform_division), 0);
        }

    }

    /**
     * @param int $type 0: 系统自动确认 1：用户手动确认
     */
    public static function confirm_recived(WxShopOrder $shop_order, $type = 0){
        if(_empty_($shop_order)){
            return false;
        }

        DB::beginTransaction();
        try {
            // todo:
            // 邀请收益
            OrderUtils::userInviteBenefitProcess(0, $shop_order->id);
            // 商品分账
            self::deal_shop_goods_ledger($shop_order->id);

            // 处理商家分成
            if($shop_order->seller_user_id > 0){
                if($shop_order->order_amount_coin > 0){
                    // 针对兑换商品

                    $coin_type = 24;
                    if($shop_order->order_from == 7){
                        $coin_type = 25;
                    }

                    $total_coins = 0;
                    WxShopOrderGoods::where([
                        ['order_id', '=', $shop_order->id], ['state', '=', 0], ['credit_type', '=', 0]
                    ])->get()->map(function ($orderGood) use (&$total_coins){
                        $total_coins += (int)($orderGood->recharge * self::get_goods_seller_division($orderGood) * 0.01);
                    });
                    $total_coins = (int)$total_coins;
                    if($total_coins >= 1){
                        UserUtils::update_user_coins($shop_order->seller_user_id, $coin_type, $total_coins, '兑换商品被购买，'.Settings::get('app_coin_name', '硬币').'+'.$total_coins);
                    }
                }else{

                    $financial_type = 26;
                    if($shop_order->order_from == 7){
                        $financial_type = 28;
                    }

                    $total_balance = 0;
                    $the_used_good_id = 0;
                    $the_bureau_good_id = 0;
                    WxShopOrderGoods::where([
                        ['order_id', '=', $shop_order->id], ['state', '=', 0], ['credit_type', '=', 1]
                    ])->get()->map(function ($orderGood) use (&$total_balance, &$the_used_good_id, &$the_bureau_good_id){
                        $total_balance += round($orderGood->recharge * self::get_goods_seller_division($orderGood) * 0.01, 2);
                        if($orderGood->goods_type == 6){
                            $the_used_good_id = $orderGood->goods_id;
                        }else if($orderGood->goods_type == 7){
                            $the_bureau_good_id = $orderGood->goods_id;
                        }
                    });
                    if($total_balance >= 0.01){
                        if($shop_order->order_from == 6){
                            UserUtils::update_user_financial($shop_order->seller_user_id, 25, $total_balance, '您的闲置商品「id:<a href="/pagesU/used-mall/detail/index?id='.$the_used_good_id.'">'.$the_used_good_id.'</a>」交易已完成，您获得余额￥'.$total_balance);
                            WxUsedGood::where('id', $the_used_good_id)->update(['status' => 3]);
                        }else{
                            $object_name = '店铺';
                            if($shop_order->order_from == 7){
                                $object_name = '俱乐部';
                            }
                            UserUtils::update_user_financial($shop_order->seller_user_id, $financial_type, $total_balance, '您的'.$object_name.'「<a href="/pagesS/sellers/sales/sales">订单'.$shop_order->order_id.'</a>」已结算，收入金额￥'.$total_balance);
                        }
                    }
                }
            }

            $confirm_time = date('Y-m-d H:i:s', time());
            WxShopOrder::where('id', $shop_order->id)->update([
                'confirm_time' => $confirm_time,
                'status' => 3,
            ]);

            if($type == 0){
                UserUtils::add_user_notice(6003, $shop_order->user_id, '商品已自动确认收货', '您的商城订单（id:'.$shop_order->id.'）发货已超过15天，系统已经为您自动确认收货，期待您的好评', 100, '', $shop_order->id);
            }
            DB::commit();
            return true;
        } catch (\Exception $e) {
            DB::rollBack();
            _logger_(__file__, __line__, $e->getMessage());
            return false;
        }
    }


    public static function deal_shop_goods_ledger($shop_order_id){
        //
        global $__MINI_GLOBAL_PAYCODE_23__;
        if(!$__MINI_GLOBAL_PAYCODE_23__){
            return;
        }

        $orderGoods = WxShopOrderGoods::where([
            ['order_id', '=', $shop_order_id], ['state', '=', 0]
        ])->whereNotIn('goods_type', array_keys(FieldUtils::getShopGoodTypes(false)))->get();

        if($orderGoods->isEmpty()){
            return;
        }

        $orderGoods->map(function ($v) use ($shop_order_id){
            $users_ledger = WxShopGoods::where('id', $v->goods_id)->value('users_ledger');
            if(!_empty_($users_ledger)){
                $users_ledger = json_decode($users_ledger, true);
                if(_empty_($users_ledger)){
                    return;
                }
                foreach ($users_ledger as $item){
                    if(_empty_(_array_key($item, 'user_id', 0)) || _empty_(_array_key($item, 'rate', 0))){
                        _logger_(__file__, __line__, $v->goods_id . ' user_ledger不合法');
                        return;
                    }
                    $order_good_recharge = WxShopOrderGoods::where([
                        ['order_id', '=', $shop_order_id],
                        ['goods_id', '=', $v->goods_id],
                        ['state', '=', 0]
                    ])->value('recharge');
                    if($order_good_recharge > 0){
                        $recharge_division = round(  $order_good_recharge * $item['rate'] * 0.01, 2);
                        if($recharge_division >= 0.01){
                            UserUtils::update_user_financial($item['user_id'], 20, $recharge_division,
                                    '您获得一笔来自商品(id：<a href="/pagesA/shop/goods-details/goods-details?id='.$v->goods_id.'">'.$v->goods_id.'</a>)的分账，该商品共消费￥'.$order_good_recharge.'，您获得其中'.$item['rate'].'%');
                        }
                    }
                }
            }
        });
    }


    /**
     * @param $shop_order_id
     * @return bool 返回是否处理完成
     */
    public static function deal_shop_order_freeze($shop_order_id){
        if(_empty_($shop_order_id)){
            return false;
        }
        $shop_order_freezed = get_shop_order_meta($shop_order_id, 'freeze_ids', 'j');
        if($shop_order_freezed){
            DB::beginTransaction();
            try {
                // todo:
                foreach ($shop_order_freezed as $freeze_id){
                    $freeze_obj = WxUserFinancialFreeze::find($freeze_id);
                    if($freeze_obj->freeze_status != 0){
                        DB::rollBack();
                        _logger_(__file__, __line__, '出现了出现了重复解冻的情况，冻结id：'.$freeze_id.'，订单id：'.$shop_order_id);
                        return false;
                    }
                    $para = json_decode($freeze_obj->para, true);
                    if($freeze_obj){
                        $r = UserUtils::update_user_financial($freeze_obj->user_id, $para['type'], $freeze_obj->freeze_amout, $para['tip']);
                        if($r){
                            $freeze_obj->freeze_status = 1;
                            $freeze_obj->save();
                        }else{
                            DB::rollBack();
                            _logger_(__file__, __line__, '出现了解冻时更新余额失败的情况，冻结id：'.$freeze_id.'，订单id：'.$shop_order_id);
                            return false;
                        }
                    }else{
                        DB::rollBack();
                        _logger_(__file__, __line__, '出现了冻结记录不存在的情况，冻结id：'.$freeze_id.'，订单id：'.$shop_order_id);
                        return false;
                    }

                }
                update_shop_order_meta($shop_order_id, 'freeze_ids', null, 'j');
                DB::commit();
                return true;
            } catch (\Exception $e) {
                DB::rollBack();
                _logger_(__file__, __line__, $e->getMessage());
                return false;
            }
        }
        return true;
    }

    public static function user_cart_count($user_id){
        if(_empty_($user_id)){
            return 0;
        }
        return WxShopCart::where('user_id', $user_id)->where('state', 0)->count();
    }

    public static function get_order_count($user_id, $seller = false){
        if(_empty_($user_id)){
            return null;
        }

        if($seller){
            $payCount = WxShopOrder::where('seller_user_id', $user_id)
                ->where('pay_status', 1)->where('status', 0)
                ->count();

            $deliverCount = WxShopOrder::where('seller_user_id', $user_id)
                ->where('pay_status', 2)->where('status', 1)
                ->count();


            $closedCount = WxShopOrder::where('seller_user_id', $user_id)
                ->where('pay_status', 2)->where('status', 2)
                ->count();


            $refundCount = WxShopOrderGoods::select('order_id')->whereIn('state', [1,2])->whereIn('order_id', function ($query) use($user_id){
                $query->select('id')->from('wx_shop_order')->where('seller_user_id', $user_id)->whereIn('status', [1, 2, 7]);
            })->distinct()->count();

            return [
                'payCount' => $payCount,
                'deliverCount' => $deliverCount,
                'closedCount' => $closedCount,
                'refundCount' => $refundCount
            ];
        }else{
            $payCount = WxShopOrder::where('user_id', $user_id)
                ->where('pay_status', 1)->where('status', 0)
                ->count();

            $deliverCount = WxShopOrder::where('user_id', $user_id)
                ->where('pay_status', 2)->where('status', 1)
                ->count();


            $closedCount = WxShopOrder::where('user_id', $user_id)
                ->where('pay_status', 2)->where('status', 2)
                ->count();

            return [
                'payCount' => $payCount,
                'deliverCount' => $deliverCount,
                'closedCount' => $closedCount,
            ];
        }
    }


    public static function generate_payway_text($vip_discount = 0,$vip_discount_coin = 0, $weixin_pay = 0, $alipay = 0, $blance_pay = 0, $coin_pay = 0, $apple_pay = 0, $yi_pay = 0,  $is_luckdraw = false, $is_taskreward = false){
        $text = '';
        if($vip_discount > 0){
            $text .= '会员优惠￥'.$vip_discount;
        }
        if($weixin_pay > 0){
            if(!_empty_($text)){
                $text .= '+';
            }
            $text .= '微信￥'.$weixin_pay;
        }
        if($alipay > 0){
            if(!_empty_($text)){
                $text .= '+';
            }
            $text .= '支付宝￥'.$alipay;
        }
        if($blance_pay > 0){
            if(!_empty_($text)){
                $text .= '+';
            }
            $text .= '余额￥'.$blance_pay;
        }
        if($coin_pay > 0){
            if(!_empty_($text)){
                $text .= '+';
            }
            $text .= Settings::get('app_coin_name', '硬币').$coin_pay;
        }
        if($apple_pay > 0){
            if(!_empty_($text)){
                $text .= '+';
            }
            $text .= '苹果支付￥'.$apple_pay;
        }
        if($yi_pay > 0){
            if(!_empty_($text)){
                $text .= '+';
            }
            $text .= '支付￥'.$yi_pay;
        }
        if($is_luckdraw){
            if(!_empty_($text)){
                $text .= '+';
            }
            $text .= '抽奖奖励';
        }
        if($is_taskreward){
            if(!_empty_($text)){
                $text .= '+';
            }
            $text .= '任务奖励';
        }
        return $text;
    }

    public static function split_shop_order_by_seller($order_id){
        $wxShopOrder = WxShopOrder::find($order_id);
        // 默认金币商品不支持加入购物车，所以无需分拆订单
        // 分拆订单后，还需要通知店铺有订单

        if($wxShopOrder && $wxShopOrder->id > 0){
            if($wxShopOrder->pay_status == 2){
                // 第一步：先按照商家拆 第二步：同个商家的订单中，按照商品类型拆
                $seller_user_id_arr = WxShopOrderGoods::where('order_id', $wxShopOrder->id)->where('credit_type', 1)->pluck('seller_user_id')->toArray();
                if($seller_user_id_arr && is_array($seller_user_id_arr)){
                    $seller_user_id_arr = array_unique($seller_user_id_arr);
                }
                if($seller_user_id_arr && count($seller_user_id_arr) > 1){
                    $seller_user_goods = [];

                    $goods_recharge_total = 0;
                    WxShopOrderGoods::where('order_id', $wxShopOrder->id)->where('credit_type', 1)->get()->map(function ($v) use (&$seller_user_goods, &$goods_recharge_total, $wxShopOrder){
                        if(!isset($seller_user_goods[$v->seller_user_id]) || !is_array($seller_user_goods[$v->seller_user_id])){
                            $seller_user_goods[$v->seller_user_id] = [
                                'goods' => [],
                                'goods_id' => [],
                                'recharge_amount' => 0,
                                'price_amount' => 0,
                                'vip_price_amount' => 0,

                                // 待下面根据比例计算
                                'coins_num_total' => 0,
                                'coins_pay_total' => 0,
                                'rechare_rate' => 0,
                            ];
                        }
                        $seller_user_goods[$v->seller_user_id]['goods'][] = $v;
                        $seller_user_goods[$v->seller_user_id]['goods_id'][] = $v->goods_id;
                        $seller_user_goods[$v->seller_user_id]['recharge_amount'] += $v->recharge;
                        $seller_user_goods[$v->seller_user_id]['price_amount'] += $v->price;
                        $seller_user_goods[$v->seller_user_id]['vip_price_amount'] += $v->vip_price;
                        $goods_recharge_total += $v->recharge;
                    });
                    if($goods_recharge_total != ($wxShopOrder->order_amount)){
                        // 先核算一遍，所有的商品价格加起来是否等于总价
                        _logger_(__file__, __line__, '订单中商品总价与订单总价不匹配,订单id：'.$wxShopOrder. ' (商品总和：'.$goods_recharge_total.' 订单总额：'.$wxShopOrder->order_amount.')');
                        return false;
                    }
                    // 先把商品分给对应的商家
                    DB::beginTransaction();
                    try {
                        if(_empty_($wxShopOrder->coins_num)){
                            // 全是人民币
                            if($seller_user_goods){
                                foreach ($seller_user_goods as $seller_user_id => $item){
                                    $orderSn = Utils::getSn(1);//生成订单号
                                    $discounts_amount = $item['price_amount'] - $item['vip_price_amount'];
                                    if($discounts_amount < 0.01){
                                        $discounts_amount = 0;
                                    }else{
                                        $discounts_amount = round($discounts_amount, 2);
                                    }
                                    $order_model = new WxShopOrder();
                                    $order_model->parent_order_id = $wxShopOrder->id;
                                    $order_model->user_id = $wxShopOrder->user_id;
                                    $order_model->order_id = $orderSn;//订单号
                                    $order_model->goods_amount = $item['price_amount'];//商品总价
                                    $order_model->discounts_amount = $discounts_amount;//优惠金额
                                    $order_model->order_amount = $item['recharge_amount'];//订单总额
                                    $order_model->adds_id = $wxShopOrder->adds_id;//收货地址id
                                    $order_model->adds_name = $wxShopOrder->adds_name;//收货人姓名
                                    $order_model->adds_mobile = $wxShopOrder->adds_mobile;//收货人电话
                                    $order_model->address = $wxShopOrder->address;//收货详细地址
                                    $order_model->user_remark = $wxShopOrder->user_remark;//用户备注
                                    $order_model->pay_status = $wxShopOrder->pay_status;//支付状态 1=未付款 2=已付款 3=已退款
                                    $order_model->status = $wxShopOrder->status;//发货状态 0=正常 1=未发货 2=已发货 3=确认收货 4=已退货 5=取消
                                    $order_model->order_from = $wxShopOrder->order_from;
                                    $order_model->order_goods_id = $item['goods_id'];
                                    $order_model->seller_user_id = $seller_user_id;
                                    $order_model->pay_way = ShopUtils::generate_payway_text($discounts_amount, 0,
                                        ($wxShopOrder->serial_platform === 0 ? $item['recharge_amount'] : 0),
                                        ($wxShopOrder->serial_platform === 1 ? $item['recharge_amount'] : 0),
                                        ($wxShopOrder->serial_platform === null ? $item['recharge_amount'] : 0),
                                        0,
                                        ($wxShopOrder->serial_platform === 3 ? $item['recharge_amount'] : 0),
                                        ($wxShopOrder->serial_platform === 2 ? $item['recharge_amount'] : 0)
                                    );
                                    $r = $order_model->save();
                                    if($r){
                                        $order_id = $order_model->id;
                                        $item_order_goods = $item['goods'];
                                        if($item_order_goods){
                                            foreach ($item_order_goods as $good){
                                                WxShopOrderGoods::where('id', $good->id)->update([
                                                    'order_id' => $order_id
                                                ]);
                                            }
                                            $wxShopOrder->delete();
                                        }
                                    }else{
                                        DB::rollBack();
                                        _logger_(__file__, __line__, '新增订单失败');
                                        return false;
                                    }
                                }
                            }
                        }else{
                            if($seller_user_goods){
                                $old_coins_num = $wxShopOrder->coins_num;
                                $old_coins_pay = $wxShopOrder->coins_pay;

                                $last_coins_num = $old_coins_num;
                                $last_coins_pay = $old_coins_pay;
                                for ($i = 0; $i < count($seller_user_goods) - 1; $i++){
                                    $seller_user_goods[$i]['rechare_rate'] = round($seller_user_goods[$i]['recharge_amount'] / $wxShopOrder->order_amount, 2);
                                    $seller_user_goods[$i]['coins_num_total'] = (int)($seller_user_goods[$i]['rechare_rate'] * $old_coins_num);
                                    $seller_user_goods[$i]['coins_pay_total'] = floorDecimal(($seller_user_goods[$i]['rechare_rate'] * $old_coins_pay), 2);
                                    $last_coins_num = $last_coins_num - $seller_user_goods[$i]['coins_num_total'];
                                    $last_coins_pay = $last_coins_pay - $seller_user_goods[$i]['coins_pay_total'];
                                }
                                $seller_user_goods[count($seller_user_goods) - 2]['coins_num_total'] = $last_coins_num;
                                $seller_user_goods[count($seller_user_goods) - 2]['coins_pay_total'] = $last_coins_pay;

                                foreach ($seller_user_goods as $seller_user_id => $item){
                                    $orderSn = Utils::getSn(1);//生成订单号
                                    $discounts_amount =  $item['price_amount'] - $item['vip_price_amount'];
                                    if($discounts_amount < 0.01){
                                        $discounts_amount = 0;
                                    }else{
                                        $discounts_amount = round($discounts_amount, 2);
                                    }
                                    $order_model = new WxShopOrder();
                                    $order_model->parent_order_id = $wxShopOrder->id;
                                    $order_model->user_id = $wxShopOrder->user_id;
                                    $order_model->order_id = $orderSn;//订单号
                                    $order_model->goods_amount = $item['price_amount'];//商品总价
                                    $order_model->discounts_amount = $discounts_amount;//优惠金额
                                    $order_model->order_amount = $item['recharge_amount'];//订单总额
                                    $order_model->adds_id = $wxShopOrder->adds_id;//收货地址id
                                    $order_model->adds_name = $wxShopOrder->adds_name;//收货人姓名
                                    $order_model->adds_mobile = $wxShopOrder->adds_mobile;//收货人电话
                                    $order_model->address = $wxShopOrder->address;//收货详细地址
                                    $order_model->user_remark = $wxShopOrder->user_remark;//用户备注
                                    $order_model->pay_status = $wxShopOrder->pay_status;//支付状态 1=未付款 2=已付款 3=已退款
                                    $order_model->status = $wxShopOrder->status;//发货状态 0=正常 1=未发货 2=已发货 3=确认收货 4=已退货 5=取消
                                    $order_model->order_from = $wxShopOrder->order_from;
                                    $order_model->order_goods_id = $item['goods_id'];
                                    $order_model->seller_user_id = $seller_user_id;
                                    $order_model->coins_num = $item['coins_num_total'];
                                    $order_model->coins_pay = $item['coins_pay_total'];

                                    $recharge_amount = $item['recharge_amount'] - $item['coins_pay_total'];
                                    if($recharge_amount < 0.01){
                                        $recharge_amount = 0;
                                    }

                                    $order_model->pay_way = ShopUtils::generate_payway_text($discounts_amount, 0,
                                        ($wxShopOrder->serial_platform === 0 ? $recharge_amount : 0),
                                        ($wxShopOrder->serial_platform === 1 ? $recharge_amount : 0),
                                        ($wxShopOrder->serial_platform === null ? $recharge_amount : 0),
                                        $item['coins_num_total'] > 0 ? $item['coins_num_total'] : 0,
                                        ($wxShopOrder->serial_platform === 3 ? $recharge_amount : 0),
                                        ($wxShopOrder->serial_platform === 2 ? $recharge_amount : 0)
                                    );
                                    $r = $order_model->save();
                                    if($r){
                                        $order_id = $order_model->id;
                                        $item_order_goods = $item['goods'];
                                        if($item_order_goods){
                                            foreach ($item_order_goods as $good){
                                                WxShopOrderGoods::where('id', $good->id)->update([
                                                    'order_id' => $order_id
                                                ]);
                                            }
                                            $wxShopOrder->delete();
                                        }
                                    }else{
                                        DB::rollBack();
                                        _logger_(__file__, __line__, '新增订单失败');
                                        return false;
                                    }
                                }
                            }
                        }
                        DB::commit();
                        return true;
                    } catch (\Exception $e) {
                        DB::rollBack();
                        _logger_(__file__, __line__, $e->getMessage());
                        return false;
                    }
                }

                if($seller_user_id_arr && is_array($seller_user_id_arr)){
                    foreach ($seller_user_id_arr as $seller_id){
                        UserUtils::assistant_notice($seller_id, '您的店铺有新的订单，请登录后台查看');
                    }
                }

            }
        }

    }


    public static function coupon_to_finish(WxShopOrder &$shopOrder, $scanner, $remark){
        DB::beginTransaction();
        try {
            // todo:
            $ship_at = date('Y-m-d H:i:s', time());
            WxShopOrder::where('id', $shopOrder->id)->update([
                'remark' => $remark,
                'ship_at' => $ship_at,
                'status' => 2,
            ]);

            $coupon_updates = [
                'status' => 1,
                'scan_at' => current_time()
            ];
            if($scanner > 0){
                $coupon_updates['scanner'] = $scanner;
            }
            WxShopOrderCoupon::where('order_id', $shopOrder->id)->update($coupon_updates);

            // 处理售后的催货
            WxShopOrderAfter::where([
                ['order_id', '=', $shopOrder->id],
                ['title', '=', '催发货']
            ])->update([
                'state' => 1,
            ]);

            Cache::forget('total:todo:count');
            Cache::forget('total:tenant:todo:count');

            ShopUtils::confirm_recived($shopOrder, 1);

            DB::commit();
            return true;
        } catch (\Exception $e) {
            DB::rollBack();
            _logger_(__file__, __line__, $e->getMessage());
            return false;
        }
    }


    // 获取商品订单的一句话描述
    public static function get_order_item_desc(WxShopOrder &$shopOrder){
        $item_desc = '';
        $child_orders = [$shopOrder->id];
        if(_empty_($shopOrder->parent_order_id)){
            $child_orders_ = WxShopOrder::where('parent_order_id', $shopOrder->id)->pluck('id')->toArray();
            if(_empty_($child_orders_)){
                foreach ($child_orders_ as $child_order_id){
                    $child_orders[] = $child_order_id;
                }
            }
        }

        WxShopOrderGoods::whereIn('order_id', $child_orders)->where('state', 0)->get()->map(function ($good) use (&$item_desc){
            if(!_empty_($item_desc)){
                $item_desc .= ' ';
            }
            $item_desc .= $good->name . '('.$good->product.'*'.$good->quantity.')';
        });
        return $item_desc;
    }


    public static function order_buys_and_stock($order_id){
        $child_orders = WxShopOrder::where('parent_order_id', $order_id)->pluck('id')->toArray();
        if(!_empty_($child_orders)){
            foreach ($child_orders as $child_order){
                self::order_buys_and_stock($child_order);
            }
            return;
        }
        $wxShopOrder = WxShopOrder::find($order_id);
        if($wxShopOrder->pay_status == 2){
            // 更新购买数
            WxShopOrderGoods::where('order_id', $wxShopOrder->id)->whereIn('goods_type', array_keys(FieldUtils::getShopGoodTypes()))->get()->map(function ($v){
                WxShopGoods::where('id', $v->goods_id)->increment('buys', (int)($v->quantity));
                WxShopGoodsProduct::where('id', $v->product_id)->decrement('stock', (int)($v->quantity));
            });
        }
    }

    public static function split_shop_order_by_type($order_id){
//        $wxShopOrder = WxShopOrder::find($order_id);
//        // 有可能有子级订单，得分两种情况 todo:
//        if($wxShopOrder && $wxShopOrder->id > 0){
//            if($wxShopOrder->pay_status == 2){
//                // 假设已经分拆好了
//            }
//        }
    }


    public static function shop_process(WxShop &$wxShop){
        global $__MINI_GLOBAL_CURRENT_USER_ID__;
        if($wxShop){
            $user = UserUtils::get_cached_user($wxShop->user_id);
            if(_empty_($wxShop->shop_name)){
                $wxShop->shop_name = $user['user_name'] . '的店';
            }
            if(_empty_($wxShop->shop_logo)){
                $wxShop->shop_logo = $user['user_avatar'];
            }
            $wxShop->follow_count = (WxShopFollow::where('shop_id', $wxShop->id)->where('status', 1)->count()) ?: 0;
            if($__MINI_GLOBAL_CURRENT_USER_ID__ > 0){
                $wxShop->is_follow = WxShopFollow::where('user_id', $__MINI_GLOBAL_CURRENT_USER_ID__)->where('shop_id', $wxShop->id)->where('status', 1)->exists();
            }else{
                $wxShop->is_follow = false;
            }
            $wxShop->shop_type_name = [1=> '个人店', 2=> '个体户', 3=>'企业店', 4=>'旗舰店/专卖店'][$wxShop->shop_type];

        }
    }


    public static function goods_filter($is_tenant, $follow, $ids, $types, $orderBy, $order, $master){
        global $__MINI_GLOBAL_CURRENT_USER_ID__,$__MINI_GLOBAL_TENANT_ID__;
        if(!in_array($follow, [0, 1, 2])){
            return null;
        }
        if(!in_array($orderBy, ['created_at', 'order', 'last_enter_at', 'follow_shop_at', 'buys'])){
            return null;
        }
        if(!in_array($order, ['desc', 'asc'])){
            return null;
        }
        if(_empty_($ids)){
            $ids = [];
        }
        $query = WxShopGoods::where('id', '>', 0);
        if($is_tenant){
//            $query = $query->where('tenant_id', $__MINI_GLOBAL_TENANT_ID__);
        }
        if($master == 1){
            $query = $query->where('user_id', $__MINI_GLOBAL_CURRENT_USER_ID__);
        }

        if($types){
            $query = $query->whereIn('type', $types);
        }

        // 处理follow
        if($follow == 1){
            if($orderBy == 'follow_shop_at'){
                $shop_ids = WxShopFollow::where([['user_id', '=', $__MINI_GLOBAL_CURRENT_USER_ID__], ['status', '=', 1]])->orderBy('updated_at', 'desc')->pluck('circle_id')->toArray();
                $query->whereIn('shop_id', $shop_ids)->orderBy(DB::raw('FIND_IN_SET(id, "' . implode(",", $shop_ids) . '"' . ")"), $order);
            }else{
                $shop_ids = WxShopFollow::where([['user_id', '=', $__MINI_GLOBAL_CURRENT_USER_ID__], ['status', '=', 1]])->orderBy('updated_at', 'desc')->pluck('circle_id')->toArray();
                $query = $query->whereIn('shop_id', $shop_ids);
            }
        }else if($follow == 2){
            $shop_ids = WxShopFollow::where([['user_id', '=', $__MINI_GLOBAL_CURRENT_USER_ID__], ['status', '=', 1]])->orderBy('updated_at', 'desc')->pluck('circle_id')->toArray();
            $query->whereNotIn('shop_id', $shop_ids);
        }

        // 处理tag
        if($ids){
            $query = $query->whereIn('id', $ids);
        }

        if(in_array($orderBy, ['created_at','last_enter_at', 'order', 'buys'])){
            // 变种orderBy
            if($orderBy == 'order'){
                $query = $query->orderBy('order', $order);
            }else if($orderBy == 'buys'){
                $query = $query->orderBy('buys', $order);
            }else if($orderBy == 'created_at'){
                $query = $query->orderBy('created_at', $order);
            }else if($orderBy == 'last_enter_at'){
                $object_ids = WxUserVisit::where([['user_id','=', $__MINI_GLOBAL_CURRENT_USER_ID__],['type', '=', 3]])->orderBy('updated_at', $order)->limit(100)->pluck('object_id');
                if($object_ids) {
                    $query = $query->whereIn('id', $object_ids)->orderBy(DB::raw('FIND_IN_SET(id, "' . implode(",", $object_ids->toArray()) . '"' . ")"));
                }
            }
        }

        if(false){

        }else{
            $query = $query->where('state', 1);
        }

        $data = $query->simplePaginate(10);
        if($data){
            $data->map(function ($v) use ($__MINI_GLOBAL_CURRENT_USER_ID__){

                if($v->contact_id &&  $v->contact_id > 0){
                    $v->contact = WxShopContact::find($v->contact_id);
                    if(_empty_($v->distance)){
                        if($__MINI_GLOBAL_CURRENT_USER_ID__ > 0){
                            $v->distance = UserUtils::distance($__MINI_GLOBAL_CURRENT_USER_ID__, $v->contact['longitude'], $v->contact['latitude']);


                            if($v->distance && $v->distance > 0){
                                if($v->distance < 10){
                                    $v->distance = '<10m';
                                }else if($v->distance >= 1000 && $v->distance <= 200000){
                                    $v->distance = '<'. round($v->distance / 1000, 2).'km';
                                }else if($v->distance > 200000){
                                    $v->distance = round($v->distance / 1000, 2).'km';
                                }else{
                                    $v->distance = '<'.(int)$v->distance.'m';
                                }
                            }else{
                                $v->distance = '';
                            }
                        }
                    }
                }

                // 处理时间
                $service_time_tip = '';
                if($v->service_time_start && $v->service_time_end){
                    $service_time_tip .= $v->service_time_start.'到'.$v->service_time_end;
                }
                if($v->service_date_start){
                    if($service_time_tip){
                        $service_time_tip = ' '.$service_time_tip;
                    }
                    if(_empty_($v->service_date_end)){
                        if($service_time_tip){
                            $service_time_tip = $v->service_date_start . $service_time_tip;
                        }else{
                            $service_time_tip = $v->service_date_start.'全天';
                        }

                    }else{
                        $service_time_tip = ($v->service_date_start . '至' . $v->service_date_end) . $service_time_tip;
                    }
                }else{
                    if($service_time_tip){
                        if($service_time_tip){
                            $service_time_tip = ' '.$service_time_tip;
                        }
                        $service_time_tip = '每天' . $service_time_tip;
                    }
                }
                $v->service_time_tip = $service_time_tip;
            });
        }

        return $data;
    }


    public static function used_process(WxUsedGood &$used_good){
        global $__MINI_GLOBAL_CURRENT_USER_ID__;
        $used_good->user = UserUtils::get_cached_user($used_good->user_id, true);
        if($used_good->user && $used_good->user['phone']){
            $used_good->contact_phone = _get_origin_attribute('wx_user', [['id', '=', $used_good->user['id']]], 'phone');
        }
        if(_empty_($used_good->distance)){
            if($__MINI_GLOBAL_CURRENT_USER_ID__ > 0){
                $used_good->distance = UserUtils::distance($__MINI_GLOBAL_CURRENT_USER_ID__, $used_good->longitude, $used_good->latitude);
            }
        }

        if($used_good->distance && $used_good->distance > 0){
            if($used_good->distance < 10){
                $used_good->distance = '<10m';
                $used_good->distance_name = $used_good->district;
            }else if($used_good->distance >= 1000 && $used_good->distance <= 200000){
                $used_good->distance = '<'. round($used_good->distance / 1000, 2).'km';
                $used_good->distance_name = $used_good->city;
            }else if($used_good->distance > 200000){
                $used_good->distance = round($used_good->distance / 1000, 2).'km';
                $used_good->distance_name = $used_good->province;
            }else{
                $used_good->distance = '<'.(int)$used_good->distance.'m';
                $used_good->distance_name = $used_good->district;
            }
        }else{
            $used_good->distance = '';
            $used_good->distance_name = $used_good->district;
        }
        if(_empty_($used_good->distance_name)){
            $used_good->distance_name = '';
        }

        if($used_good->image_urls){
            $used_good->pic = _array_key($used_good->image_urls[0], 'url', '') . '?imageMogr2/thumbnail/600x/format/webp/interlace/1';

            $used_good->pic_width = _array_key($used_good->image_urls[0], 'width', '');
            $used_good->pic_height = _array_key($used_good->image_urls[0], 'height', '');


            if($used_good->pic_width > 0){
                $old_widht = $used_good->pic_width;
                $used_good->pic_width = 363;
                $used_good->pic_height = (int)( (363 * $used_good->pic_height) / $old_widht );
            }
        }

        if(_empty_($used_good->pic)){
            if($used_good->video_cover){
                $used_good->pic = $used_good->video_cover;
            }else{
                $used_good->pic = Settings::get('img_share_default', '');
            }
        }

        if(_empty_($used_good->pic_height)){
            $used_good->pic_height = 500;
        }


        $used_good->location = [
            'latitude' => $used_good->latitude,
            'longitude' => $used_good->longitude,
            'address_name' => $used_good->address_name,
            'address_detailed' => $used_good->address_detailed
        ];

        if($used_good->classify_id > 0){
            $used_good->classify = WxUsedClassify::find($used_good->classify_id);
        }

        if($used_good->is_express_delivery == 1){
            if($used_good->express_cost == 0){
                if($used_good ->is_self_pickup == 1){
                    $used_good->tip = '自提或包邮';
                }else{
                    $used_good->tip = '包邮';
                }
            }else{
                if($used_good ->is_self_pickup == 1){
                    $used_good->tip = '自提或邮费￥'.$used_good->express_cost;
                }else{
                    $used_good->tip = '邮费￥'.$used_good->express_cost;
                }
            }
        }else{
            if($used_good ->is_self_pickup == 1){
                $used_good->tip = '仅自提';
            }else{
                $used_good->tip = '';
            }
        }

        $used_good->markers = [
            ['latitude'=>$used_good->latitude, 'longitude'=>$used_good->longitude]
        ];

        $used_good->format_time = format_datetime($used_good->created_at);
        $used_good->comment_count = WxUsedComment::where('used_good_id', $used_good->id)->count();
        if(_empty_($used_good->comment_count)){
            $used_good->comment_count = 0;
        }
        $used_good->needed_count = WxUsedNeed::where('used_good_id', $used_good->id)->where('status', 1)->count();
        if(_empty_($used_good->needed_count)){
            $used_good->needed_count = 0;
        }
    }

    public static function appstore_module_process($order_id){

        if(get_mini_domain() != 'mini.minisns.cn'){
            return ;
        }

        $goods_ids = [];
        WxShopOrderGoods::where('order_id', $order_id)->get(['goods_id'])->map(function ($v) use (&$goods_ids){
            $goods_ids[] = $v->goods_id;
            return $v;
        });

        $oinfo = WxShopOrder::withTrashed()->where('id', $order_id)->first();
        $uid = $oinfo['user_id'];

        $model_paycode_map = [
            2473 => 1,
            2474 => 2,
            2477 => 3,
            2475 => 4,
            2472 => 5,
            2476 => 6,
            2478 => 7,
            2479 => 8,
            2480 => 9,
            2481 => 10,
            2482 => 11,
            2483 => 12,
            2733 => 13,
            2484 => 14,
            2794 => 15,
            2680 => 16,
            2492 => 17,
            2551 => 18,
            2573 => 19,
            2669 => 20,
            2715 => 21,
            2719 => 22,
            2722 => 23,
            2729 => 24,
            2776 => 25,
            2740 => 26,
            2748 => 27,
            2797 => 28,
            2805 => 29,
            2817 => 30,
            2824 => 31,
            2886 => 32,
            2895 => 33,
            2897 => 34,
            2908 => 36,
            2899 => 0
        ];

        $model_keys = array_keys($model_paycode_map);

        $base_pays = [];
        $domain_auth = WxDomainAuth::where('user_id', $uid)->first();
        if($domain_auth){
            $base_pays = explode(',', $domain_auth->pays);
        }

        foreach ($goods_ids as $good_id){
            if(in_array($good_id, $model_keys) && !in_array($good_id, $base_pays)){
                $base_pays[] = $model_paycode_map[$good_id];
            }
        }
        $base_pays = array_unique($base_pays);

        if($domain_auth){
            WxDomainAuth::where('user_id', $uid)->update(['pays' => implode(',', $base_pays)]);
        }

    }

    public static function paied_content_process($order_id){
        global $__MINI_GLOBAL_PAYCODE_11__;
        if(!$__MINI_GLOBAL_PAYCODE_11__){
            return;
        }

        $child_orders = WxShopOrder::where('parent_order_id', $order_id)->pluck('id')->toArray();
        if(!_empty_($child_orders)){
            foreach ($child_orders as $child_order_id){
                self::paied_content_process($child_order_id);
            }
            return;
        }

        self::appstore_module_process($order_id);

        $goods_ids = [];
        WxShopOrderGoods::where('order_id', $order_id)->get(['goods_id'])->map(function ($v) use (&$goods_ids){
            $goods_ids[] = $v->goods_id;
            return $v;
        });
        if($goods_ids){
            $paiedContentItem = [];
            foreach ($goods_ids as $goods_id){
                $exists = WxShopGoods::where([
                    ['id', '=', $goods_id],
                ])->whereIn('type', [2, 3, 4])->first(['id', 'type','paid_content', 'download_url', 'download_version']);
                if($exists){
                    $paiedContentItem[] = $exists;
                }
            }
            if($paiedContentItem){
                // 更新订单商品的虚拟发货信息
                foreach ($paiedContentItem as $item){
                    if($item->type == 4){

                        $quantity = WxShopOrderGoods::where([
                            ['order_id', '=', $order_id],
                            ['goods_id', '=', $item->id]
                        ])->value('quantity');

                        $paid_content = $item->paid_content;
                        $paid_content_arr = explode("\n", $paid_content);
                        if(count($paid_content_arr) > $quantity){

                            $kami_str = '';
                            if($quantity >= 1){
                                for($i = 0; $i < $quantity; $i++){
                                    if(!_empty_($kami_str)){
                                        $kami_str .= '，';
                                    }
                                    $kami_str .= $paid_content_arr[$i];
                                }
                            }

                            if(_empty_($kami_str)){
                                _logger_(__file__, __line__, '卡密为空2');
                            }

                            WxShopOrderGoods::where([
                                ['order_id', '=', $order_id],
                                ['goods_id', '=', $item->id]
                            ])->update(['paid_content'=>$kami_str, 'download_url'=>$item->download_url, 'download_version'=>$item->download_version]);

                            if($quantity > 1){
                                for($i = 0; $i < $quantity; $i++){
                                    unset($paid_content_arr[$i]);
                                }
                            }else{
                                unset($paid_content_arr[0]);
                            }

                            WxShopGoods::where('id', $item->id)->update( [ 'paid_content' => implode("\n", $paid_content_arr)] );

                        }else if(count($paid_content_arr) == $quantity){

                            $kami_str = '';
                            if($quantity >= 1){
                                for($i = 0; $i < $quantity; $i++){
                                    if(!_empty_($kami_str)){
                                        $kami_str .= '，';
                                    }
                                    $kami_str .= $paid_content_arr[$i];
                                }
                            }

                            if(_empty_($kami_str)){
                                _logger_(__file__, __line__, '卡密为空2');
                            }

                            WxShopOrderGoods::where([
                                ['order_id', '=', $order_id],
                                ['goods_id', '=', $item->id]
                            ])->update(['paid_content'=>$kami_str, 'download_url'=>$item->download_url, 'download_version'=>$item->download_version]);

                            if($quantity > 1){
                                for($i = 0; $i < $quantity; $i++){
                                    unset($paid_content_arr[$i]);
                                }
                            }else{
                                unset($paid_content_arr[0]);
                            }

                            UserUtils::assistant_notice('admin', '商品(id: '.$item->id.')'.'的卡密已经售空，系统已为您下载该商品');
                            WxShopGoods::where('id', $item->id)->update( ['state' => 0, 'paid_content' => ''] );
                        }else{

                            WxShopOrderGoods::where([
                                ['order_id', '=', $order_id],
                                ['goods_id', '=', $item->id]
                            ])->update(['paid_content'=>'卡密已售空，请联系客服进行补偿', 'download_url'=>$item->download_url, 'download_version'=>$item->download_version]);
                            WxShopGoods::where('id', $item->id)->update( ['state' => 0, 'paid_content' => ''] );

                            if(count($paid_content_arr) > 0){
                                UserUtils::assistant_notice('admin', '商品(id: '.$item->id.')'.'的卡密库存不足，用户却购买了'.$quantity.'件该商品（id：'.$item->id.'），请管理员联系用户进行协商');
                            }else{
                                UserUtils::assistant_notice('admin', '商品(id: '.$item->id.')'.'的卡密已经售空，但用户却购买了该商品（id：'.$item->id.'），请管理员联系用户进行协商');
                            }


                        }

                    }else{
                        WxShopOrderGoods::where([
                            ['order_id', '=', $order_id],
                            ['goods_id', '=', $item->id]
                        ])->update(['paid_content'=>$item->paid_content, 'download_url'=>$item->download_url, 'download_version'=>$item->download_version]);
                    }
                }

                if(count($paiedContentItem) == count($goods_ids)){

                    // 全部虚拟物品
                    // 直接发货
                    $ship_at = date('Y-m-d H:i:s', time());

                    WxShopOrder::where('id', $order_id)->update([
                        'has_virtual' => 1,
                        'ship_at' => $ship_at,
                        'status' => 2,
                    ]);

                    $oinfo = WxShopOrder::where('id', $order_id)->first();

                    $nr = '您的订单：' . $oinfo['order_id'] . ' 已经自动发货，请在订单中心查看。';

                    // 发送通知
                    UserUtils::add_user_notice(6001, $oinfo['user_id'], '商品发货通知', $nr, 100, '', $order_id);
                    UserUtils::assistant_notice('admin', '用户（<a href="/pages/user/user?id='.$oinfo['user_id'].'">id：'.$oinfo['user_id'].'</a>）的商品订单'.count($goods_ids).'件虚拟物品已经自动发货。');

                }else{
                    WxShopOrder::where('id', $order_id)->update([
                        'has_virtual' => 1,
                    ]);
                }

            }
        }
    }

}
